package nl.grol.yakshop.domain.service;

import java.util.logging.Logger;

import nl.grol.yakshop.domain.model.CustomerOrder;
import nl.grol.yakshop.domain.model.ProcessedOrder;
import nl.grol.yakshop.domain.model.Stock;
import nl.grol.yakshop.domain.repository.RepositoryI;
import nl.grol.yakshop.util.YakShopException;

import com.google.common.base.Preconditions;
import com.google.inject.Inject;

public class OrderProcessor implements OrderProcessorI {
    private static final Logger LOGGER = Logger.getLogger(OrderProcessor.class.getName());

	private RepositoryI repository;
	private StockCalculatorI calculator;
	
	@Inject
	public OrderProcessor( RepositoryI repostory, StockCalculatorI calculator) {
		this.repository = repostory;
		this.calculator = calculator;
	}

	public ProcessedOrder processorOrder( CustomerOrder customerOrder, int daysSinceShopStart ) 
				throws YakShopException  {
		ProcessedOrder processedOrder = null;
		
		Preconditions.checkArgument(customerOrder != null);
		Preconditions.checkArgument(customerOrder.getMilkInLiters() != null);
		Preconditions.checkArgument(customerOrder.getMilkInLiters() >= 0, 
				"clientOrder.getMilkInLiters(): received: %s expected: >= 0", customerOrder.getMilkInLiters() );
		Preconditions.checkArgument(customerOrder.getSkins() != null);
		Preconditions.checkArgument(customerOrder.getSkins() >= 0, 
				"clientOrder.getSkins(): received: %s expected: >= 0", customerOrder.getSkins() );
		Preconditions.checkArgument(daysSinceShopStart >= 0, 
				"daysSinceShopStart: received: %s expected: >= 0", daysSinceShopStart );
		
		/*
		 * Get herd
		 */
		Stock stock = calculator.determineStockOnDay(daysSinceShopStart);

		/*
		 * Apply skin order on stock
		 *
		 * Only deliver when ordered milk is completely available
		 */
		Double orderedMilk = null;
		if( customerOrder.getMilkInLiters() <= stock.getMilk() ) {
			double remaining = stock.getMilk() - customerOrder.getMilkInLiters();
			LOGGER.info("Enough milk in stock to fullfill order: remaining:" + remaining);
			orderedMilk = customerOrder.getMilkInLiters();
		} else {
			LOGGER.info("NOT Enough milk in stock to fullfill order");
		}
		
		/*
		 * Apply skin order on stock
		 * 
		 * Only deliver when orderedskin is completely available
		 */
		Integer orderedSkins = null;
		if( customerOrder.getSkins() <= stock.getSkins() ) {
			int remaining = orderedSkins = stock.getSkins() - customerOrder.getSkins();
			LOGGER.info("Enough skins in stock to fullfill order: remaining:" + remaining );
			orderedSkins = customerOrder.getSkins();
		} else {
			LOGGER.info("NOT Enough skins in stock to fullfill order");
		}
		
		/*
		 * Composed ProcesseOorder where orderedMilk orderedSkins
		 * can be null in case of invalid stock
		 */
		processedOrder = new ProcessedOrder( daysSinceShopStart,
											 customerOrder.getReceiptDate(),
											 customerOrder.getCustomerName(), 
											 orderedMilk, orderedSkins);
		
		LOGGER.info("Processed order:" + processedOrder );
		
		repository.persistProcessedOrder(processedOrder);
		
		return processedOrder;
	}

}
